<script setup lang="ts">
import { Form } from 'ant-design-vue';
import type { CurrencyBalance } from '~/api/services/main.api';
import { noticeMeta } from '~/composables/useMeta';
import LastTransaction from '../Comps/LastTransaction.vue';
import { useWithdrawalCache } from '../ts/useWithdrawalCache';
import { filterInputNum, showWithdrawConfirm, toBnVal, toDecimalPlaces } from '../ts/utils';

const props = defineProps<{
  currencyInfo?: CurrencyBalance;
  chain?: string;
  bnBalance: ReturnType<typeof bignumber>;
  bnLockedBalance: ReturnType<typeof bignumber>;
  bnAvailableBalance: ReturnType<typeof bignumber>;
}>();

const { getCache, setCache } = useWithdrawalCache();

const formData = reactive({ address: '', amount: '' });

async function inputAmount(e: any) {
  await nextTick();
  formData.amount = filterInputNum(e.target?.value, 'float', 4);
}

function maxAmountFn() {
  const max = toDecimalPlaces(props.bnAvailableBalance, false, 4);
  if (max.gt(0)) {
    formData.amount = max.toString();
  }
}

const getTokensInfoRef = computed(() => props.chain && props.currencyInfo ? props.currencyInfo?.tokens?.find(x => x.chain === props.chain) : null);

const getServiceAmountRef = computed(() => {
  const inputVal = toBnVal(formData.amount);
  const _token = getTokensInfoRef.value;
  if (!_token || !inputVal) {
    return bignumber(0);
  }
  const _ser = toBnVal(_token.service_amount);
  if (_ser?.gt(0)) {
    return _ser;
  }
  const _rate = toBnVal(_token.service_amount_rate) || bignumber(-1);
  const _min = toBnVal(_token.min_service_amount);
  const _max = toBnVal(_token.max_service_amount);

  const result = inputVal.times(_rate);
  if (_rate.gt(0) && _min && result.lt(_min)) {
    return _min;
  }
  if (_rate.gt(0) && _max && result.gt(_max)) {
    return _max;
  }
  const _dec = Math.max(_ser?.decimalPlaces() ?? 0, _min?.decimalPlaces() ?? 0, _max?.decimalPlaces() ?? 0, 2);
  return toDecimalPlaces(result, false, _dec);
});

const getMinMaxRef = computed(() => {
  const _token = getTokensInfoRef.value;
  const bnMin = toBnVal(_token?.min_withdraw_amount);
  const _min = bnMin ? toDecimalPlaces(bnMin, false, bnMin.decimalPlaces() ?? 2) : bignumber(0);
  const _ser = toBnVal(_token?.service_amount) || bignumber(-1);
  const _minSer = toBnVal(_token?.min_service_amount) || bignumber(-1);
  const resMin = bignumber.max(_ser.gt(0) ? _ser : _minSer, _min);
  return { min: resMin, max: bignumber.max(props.bnAvailableBalance, resMin) };
});

const getReceivedAmountRef = computed(() => {
  const inputVal = toBnVal(formData.amount);
  const { min } = getMinMaxRef.value;
  if (!inputVal?.gt(0) || (min.gt(0) && inputVal.lte(min))) {
    return bignumber(0);
  }
  const _dec = Math.max(getServiceAmountRef.value.decimalPlaces() ?? 0, 2);
  return toDecimalPlaces(inputVal.minus(getServiceAmountRef.value), false, _dec);
});

const amountValidateInfo = reactive({ isError: false, text: '' });

function setAmountValidateInfo(isError = false, text = '') {
  amountValidateInfo.isError = isError;
  amountValidateInfo.text = isError ? text : '';
  return formResult();
}

const $form = Form.useForm(formData, reactive({
  address: [
    {
      validator(_: any, value: string) {
        return value ? formResult() : formResult($t('1mZrq1hNqQ7JTeeG6z3Hc'));
      },
    },
  ],
  amount: [
    {
      validator(_: any, val: string) {
        const inputVal = toBnVal(val);

        if (!inputVal || inputVal?.lte(0))
          return setAmountValidateInfo(true, $t('hWstS1hvXUnYtJxNPnio'));

        if (inputVal.gt(props.bnAvailableBalance) || props.bnAvailableBalance.lte(0))
          return setAmountValidateInfo(true, $t('oGiAq6Hya7nrnOzZfduQr'));

        const { max, min } = getMinMaxRef.value;

        if (max.gt(0) && inputVal.gt(max))
          return setAmountValidateInfo(true, $t('mkMBakhFtLGpRt9cRBaD7', { amount: max.toFormat() }));

        if (min.gt(0) && inputVal.lte(min))
          return setAmountValidateInfo(true, $t('lsLjWbuZu4iu9sNSfrG4', { amount: min.toFormat() }));

        return setAmountValidateInfo();
      },
    },
  ],
}));

watch([() => props.currencyInfo?.currency ?? '', () => props.chain], ([currency, chain]) => {
  if (currency && chain && formData.address === '') {
    formData.address = getCache(chain, currency) ?? '';
  }
  setTimeout(() => $form.clearValidate());
}, { immediate: true });

const withdrawMut = useMutation({
  mutationKey: [apis.apiFundWithdrawSubmit.id],
  mutationFn: apis.apiFundWithdrawSubmit.setDefaultConfig({ successMessage: false, errorMessage: true }),
  onSuccess: (resp, { requestBody: body }) => {
    setCache(body?.address ?? '', body?.chain ?? '', body?.currency ?? '');
    useCurrencyStore().balanceQry.refetch();
    noticeMeta().withdraw({ currency: resp.currency.currency, id: resp.address });
    antdModal.success({
      content: $t('raiIdB_7L3v3oTkkGnGbO'),
      class: 'ant-cover__confirm-modal',
      okCancel: false,
      centered: true,
    });
    globalPopups.wallet.close();
    $form.resetFields();
    $form.clearValidate();
    setAmountValidateInfo();
    return resp;
  },
});

const btnLoading = computed(() => toValue(withdrawMut.isPending));

async function handleSubmit() {
  if (await $form.validate().catch(() => false)) {
    const res = await openAuthFlowPopup('verify2FAWhenEnable').catch(() => undefined);
    showWithdrawConfirm(() => {
      withdrawMut.mutate({ requestBody: {
        ...formData,
        ...res,
        currency: props.currencyInfo?.currency ?? '',
        chain: props.chain ?? '',
      } });
    }, props.bnBalance, props.bnLockedBalance);
  }
}
</script>

<template>
  <div class="relative flex flex-1 flex-col justify-between text-sm text-sys-text-body lt-mobile:h-full">
    <div class="lt-mobile:(flex-1 overflow-y-auto)">
      <AForm @keypress.enter="handleSubmit">
        <AFormItem class="!mb-3">
          <slot />
        </AFormItem>

        <AFormItem v-bind="$form.validateInfos.address" class="!mb-3">
          <div class="mb-1.5 text-sm text-sys-text-body">
            {{ $t('xEkt2c3N9Fm7hDrCGb18V') }}
          </div>
          <AInput
            v-model:value="formData.address"
            allowClear
            :placeholder="$t('1mZrq1hNqQ7JTeeG6z3Hc')"
          />
        </AFormItem>

        <AFormItem v-bind="$form.validateInfos.amount" class="!mb-3" :validateStatus="amountValidateInfo.isError ? 'error' : 'success'">
          <div class="mb-1.5 flex-between items-end whitespace-normal break-words break-all text-sm text-sys-text-body">
            <div>{{ $t('m8mu3JTsq0mNmDfh2GDh1') }}</div>
            <div class="whitespace-normal break-words break-all text-xs">
              {{ $t('fzQWzNp8QafNxHzEvAu3F') }}：{{ bnAvailableBalance.toFormat() }}
            </div>
          </div>
          <AInput
            v-model:value="formData.amount"
            class="w-full"
            allowClear
            :placeholder="$t('qlxJcfsbDcKdovNZpjeKl')"
            inputmode="decimal"
            :maxlength="18"
            @change="inputAmount"
            @blur="inputAmount"
          >
            <template #suffix>
              <div class="cursor-pointer rounded-lg bg-sys-layer-d px-2.5 py-1.5 text-xs text-sys-text-body" @click="maxAmountFn">
                {{ $t('0mZtH3LTzAein3T28u3M') }}
              </div>
            </template>
          </AInput>
          <template #help>
            <div class="grid grid-cols-[1fr_auto] mb-2 w-full gap-4">
              <span class="text-sm text-[#dc4446]">{{ amountValidateInfo.isError ? amountValidateInfo.text : '' }}</span>
              <slot name="lockedBalance" />
            </div>
          </template>
        </AFormItem>

        <AFormItem v-if="getServiceAmountRef.gt(0) && getReceivedAmountRef.gt(0)" class="!mb-3">
          <div class="mb-1.5 text-sm text-sys-text-body">
            {{ $t('np4skhNFeYpCk9AepQq') }}
          </div>
          <div class="grid grid-cols-[auto_1fr] items-center gap-x-2 border-(1px sys-layer-e solid) rounded-lg bg-sys-layer-d px-2.5 py-1.5">
            <div class="text-xs">
              {{ $t('txnBsvvLm0IcSoZ0lYusm') }}
            </div>
            <div class="whitespace-normal break-words break-all text-right text-xl text-green font-semibold">
              {{ getReceivedAmountRef.toFormat() }}
            </div>
            <div class="text-xs">
              {{ $t('mnzMeff8rTooSapjfgwIr') }}
            </div>
            <div class="whitespace-normal break-words break-all text-right">
              {{ `${getServiceAmountRef.toFormat()} ${currencyInfo?.currency}` }}
            </div>
          </div>
        </AFormItem>

        <LastTransaction type="withdraw" />
      </AForm>
    </div>
    <div class="pt-3 lt-mobile:(mb-3 mt-auto)">
      <AButton
        class="ant-cover__Button-3d-primary w-full"
        type="primary"
        :loading="btnLoading"
        :disabled="btnLoading"
        @click="handleSubmit"
      >
        {{ $t('xQp2HJedTncmCsXifzn3') }}
      </AButton>
    </div>
  </div>
</template>
